/*=============================================================================+
|                                                                              |
| Copyright 2015                                                             |
| Montage Inc. All right reserved.                                             |
|                                                                              |
+=============================================================================*/
/*! 
*   \file app_init.c
*   \brief main entry
*   \author Montage
*/

/*=============================================================================+
| Included Files                                                               |
+=============================================================================*/
#include <event.h>
#include <common.h>
#include <net_api.h>
#include <wla_api.h>
#include <gpio.h>
#include <alink_cfg_api.h>
#if defined(CONFIG_FREERTOS)
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "timers.h"
#include "task.h"
#include "semphr.h"
#endif
#include "cJSON/cJSON.h"
#include "alink_export.h"

#define GIPO_ZCFG_RESET 6


#define Method_PostData     "postDeviceData"
#define Method_PostRawData  "postDeviceRawData"
#define Method_GetStatus    "getDeviceStatus"
#define Method_SetStatus    "setDeviceStatus"
#define Method_GetAlinkTime "getAlinkTime"

#ifdef ALINK_PASSTHROUGH
#define ALINK_METHOD_POST     Method_PostRawData
#define ALINK_GET_DEVICE_DATA ALINK_GET_DEVICE_RAWDATA
#define ALINK_SET_DEVICE_DATA ALINK_SET_DEVICE_RAWDATA
#else /*!< ALINK_PASSTHROUGH */
#define ALINK_METHOD_POST     Method_PostData
#define ALINK_GET_DEVICE_DATA ALINK_GET_DEVICE_STATUS
#define ALINK_SET_DEVICE_DATA ALINK_SET_DEVICE_STATUS
#endif /*!< ALINK_PASSTHROUGH */


enum {
    ALINK_ACTIVE_DEVICE,
    ALINK_POST_DATA,
    ALINK_CONFIG_RESET,
    ALINK_CONNECTED,
    ALINK_DISCONNECTED,
};


enum {
    ATTR_ERRORCODE_INDEX,
    ATTR_HUE_INDEX,
    ATTR_LUMINANCE_INDEX,
    ATTR_SWITCH_INDEX,
    ATTR_WORKMODE_INDEX,
    ATTR_MAX_NUMS
};
#define DEVICE_ATTRS_NUM   (ATTR_MAX_NUMS)

int device_state[] = {0, 10, 50, 1, 2};/* default value */
const char *device_attr[] = {
    "ErrorCode",
    "Hue",
    "Luminance",
    "Switch",
    "WorkMode",
    NULL
};

#define PostDataFormat      "{\"ErrorCode\":{\"value\":\"%d\"},\"Hue\":{\"value\":\"%d\"},\"Luminance\":{\"value\":\"%d\"},\"Switch\":{\"value\":\"%d\"},\"WorkMode\":{\"value\":\"%d\"}}"

#define POST_DATA_BUFFER_SIZE    (2050)
static char post_data_buffer[POST_DATA_BUFFER_SIZE];

static xQueueHandle xAlinkMsgQueue = NULL;


/*=============================================================================+
| Define                                                                       |
+=============================================================================*/

static void alink_event_init(void)
{
    xAlinkMsgQueue = xQueueCreate( 5 , sizeof(uint8_t)); 
}



static void alink_event_send(uint8_t type)
{
    xQueueSend( xAlinkMsgQueue, ( void* )&type, 0);
}


static void cloud_connected(void)
{
    alink_event_send(ALINK_CONNECTED);
}
static void cloud_disconnected(void){
    alink_event_send(ALINK_DISCONNECTED);
}


static void cloud_get_device_data(char *json_buffer)
{
    alink_event_send(ALINK_POST_DATA);
	return;
}

static int cloud_set_device_data(char *json_buffer)
{
	int i;
    cJSON *Json,*s;
	Json = cJSON_Parse(json_buffer);
	if(Json == NULL){
		return -1;
	}
    for (i = 0; device_attr[i]; i++) {
        s = cJSON_GetObjectItem(Json, device_attr[i]);
        if(s  == NULL)
        {
            continue;
        }
        device_state[i] = atoi(s->value.valuestring);
    }
    cJSON_Delete(Json);
    alink_event_send(ALINK_POST_DATA);
	return 0;
}



static void alink_key_task(void* data)
{
    uint16_t n = 0;
    for(;;){
        if(digital_read(GIPO_ZCFG_RESET) == LOW)
        {
            ++n;
        }else if(n > (10*3))
        {
            alink_event_send(ALINK_CONFIG_RESET);
            break;
        }else if(n > 2 && n < 10)
        {
            n = 0;
            alink_event_send(ALINK_ACTIVE_DEVICE);
        }else{
            n = 0;
        }

        sys_msleep(100);
    }
    vTaskDelete(NULL);
}

static void alink_key_init(void)
{
    pin_mode(GIPO_ZCFG_RESET,GPIO_IN);
    xTaskCreate(alink_key_task, (const signed char*)"key", (unsigned short) 1024, NULL, 5, NULL );
    return;
}


static void alink_event_loop_task(void)
{
    uint8_t AlinkMsg = 0;
    for(;;){
        if(pdFALSE == xQueueReceive( xAlinkMsgQueue, &AlinkMsg, portMAX_DELAY ))
        {
            continue;
        }
        switch(AlinkMsg)
        {
            case ALINK_ACTIVE_DEVICE:
            alink_activate_device();
            break;
            case ALINK_POST_DATA:
            snprintf(post_data_buffer, POST_DATA_BUFFER_SIZE, PostDataFormat,
                device_state[ATTR_ERRORCODE_INDEX],
                device_state[ATTR_HUE_INDEX],
                device_state[ATTR_LUMINANCE_INDEX],
                device_state[ATTR_SWITCH_INDEX],
                device_state[ATTR_WORKMODE_INDEX]);
            alink_report(Method_PostData, post_data_buffer);
            break;
            case ALINK_CONFIG_RESET:
            alink_config_reset();
            return;
            case ALINK_CONNECTED:
            serial_printf("alink cloud connected!\n");
            break;
            case ALINK_DISCONNECTED:
            serial_printf("alink cloud disconnected!\n");
            break;
        }
    }
}

void user_init(void)
{
	platform_debug_uart_init();	
	if(alink_device_init() < 0)
	{
		rf_config_reset();
		platform_sys_reboot();
		return;
	}
    alink_register_callback(ALINK_CLOUD_CONNECTED, &cloud_connected);
    alink_register_callback(ALINK_CLOUD_DISCONNECTED, &cloud_disconnected);
    alink_register_callback(ALINK_GET_DEVICE_DATA, &cloud_get_device_data);
    alink_register_callback(ALINK_SET_DEVICE_DATA, &cloud_set_device_data);
    alink_key_init();
    alink_event_init();
	alink_connect_ap_power_on();

	getUTCtime("time.pool.aliyun.com");
	alink_start();
    alink_wait_connect(ALINK_WAIT_FOREVER);
    alink_event_loop_task();
}
